package br.com.sistema.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaQuery;

public class GenericDAOImplements<T> implements Serializable, GenericDAO<T>{

	private static final long serialVersionUID = 1L;
	private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("sistemavendas");
	protected EntityManager em;
	private Class<T> classe;
	
	//Construtor que vai dizer qual tipo da classe esta sendo instanciada.
	public GenericDAOImplements(Class<T> classe) {
		this.classe = classe;
	}
	
	public void abrirTransacao(){
		this.em = this.emf.createEntityManager();
		this.em.getTransaction().begin();
	}
	
	public void commit(){
		this.em.getTransaction().commit();
	}
	
	public void rollback(){
		this.em.getTransaction().rollback();
	}
	
	public void fecharTransacao(){
		this.em.close();
	}
	
	public void fecharECommitarTransacao(){
		commit();
		fecharTransacao();
	}
	
	@Override
	public void salvar(Object obj){
		try {
			abrirTransacao();
			this.em.persist(obj);
			fecharECommitarTransacao();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			rollback();
		}
	}
	
	@Override
	public void atualizar(Object obj){
		try {
			abrirTransacao();
			this.em.merge(obj);
			fecharECommitarTransacao();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			rollback();
		}
	}
	
	@Override
	public void remover(Integer id){
		try {
			abrirTransacao();
			this.em.remove(this.em.getReference(classe, id));
			fecharECommitarTransacao();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			rollback();
		}
	}
	
	@Override
	public T buscar(Object obj){
		try {
			abrirTransacao();
			return this.em.find(this.classe, obj);
		} finally {
			fecharTransacao();
		} 
	}
	
	@Override
	public List<T> listar(){
		try {
			abrirTransacao();
			CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
			cq.select(cq.from(classe));
			return em.createQuery(cq).getResultList();
		} finally {
			fecharTransacao();
		}
	}
}
